package com.stylefeng.guns.core;

import com.alibaba.fastjson.JSON;
import com.stylefeng.guns.GunsApplication;
import com.stylefeng.guns.core.util.Hash;
import com.stylefeng.guns.modular.qinhe.service.ISuModelService;
import com.stylefeng.guns.modular.system.model.SuModel;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import java.util.Map;
import javax.xml.bind.DatatypeConverter;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import jodd.io.FileUtil;
import jodd.util.StringUtil;
import jodd.util.ThreadUtil;
import net.sf.sevenzipjbinding.ExtractOperationResult;
import net.sf.sevenzipjbinding.IInArchive;
import net.sf.sevenzipjbinding.SevenZip;
import net.sf.sevenzipjbinding.SevenZipException;
import net.sf.sevenzipjbinding.impl.RandomAccessFileInStream;
import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class DownloadZMTask {

  @Autowired
  ISuModelService suModelService;
  private Logger log = LoggerFactory.getLogger(this.getClass());

  @Async
  public void download(SuModel suModel, String session, String modelid, String thumbpath)
      throws IOException {
    File jarFolder = new ApplicationHome(GunsApplication.class).getDir();
    long filename = System.currentTimeMillis();
    log.info("start downloading zhimo---" + suModel.getModelname());
    File modelsFolder = new File(
        jarFolder + "/models/");
    modelsFolder.mkdirs();
    HttpRequest request =
        HttpRequest.get(
            "http://su.znzmo.com/commodityDetail/getDownLoadCommodityUrl.do?skuId=" + modelid)
                   .acceptJson()
                   .header("Cookie", "JSESSIONID=" + session + ";")
                   .header("User-Agent",
                           "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
    HttpResponse response;
    String downloadURL = "";
    for (int i = 0; i < 5; i++) {
      response = request.send();
      Map map = JSON.parseObject(response.bodyText(), Map.class);
      if ("成功".equals(map.get("msg"))) {
        downloadURL = map.get("data").toString();
        break;
      }
      ThreadUtil.sleep(500);
    }
    if (StringUtil.isBlank(downloadURL)) {
      log.error("无法下载该模型!");
      return;
    }
    response = HttpRequest.get(downloadURL).send();
    byte[] bytes = response.bodyBytes();
    File dest = new File(modelsFolder, filename + ".skp");
    if (response.mediaType().indexOf("7z-compressed") > 0) {
      File tempFile = FileUtil.createTempFile();
      FileUtil.writeBytes(tempFile, bytes);
      boolean result = extractFirstSkpFile(tempFile, dest);
      if (!result) {
        log.error("can't extract zhimo model id:" + modelid);
        return;
      }
    } else {
      if (response.bodyText().startsWith("Rar")) {
        File tempFile = FileUtil.createTempFile();
        FileUtil.writeBytes(tempFile, bytes);
        boolean result = extractFirstSkpFile(tempFile, dest);
        if (!result) {
          log.error("can't extract zhimo model id:" + modelid);
          return;
        }
      } else {
        FileUtil.writeBytes(dest, bytes);
      }
    }

    suModel.setChecksum(DatatypeConverter.printHexBinary(Hash.SHA256.checksum(dest)).toLowerCase());
    suModel.setFilename(filename + "");
    suModel.setFilesize(Files.size(dest.toPath()));
    byte[] thumbBytes = HttpRequest.get(thumbpath).send().bodyBytes();
    FileUtil.writeBytes(new File(modelsFolder, filename + ".png"), thumbBytes);
    suModelService.insert(suModel);
    log.info("finished download zhimo---" + suModel.getModelname());
  }

  private boolean extractFirstSkpFile(File zipFile, File dest) {
    RandomAccessFile randomAccessFile = null;
    IInArchive inArchive = null;
    try {
      randomAccessFile = new RandomAccessFile(zipFile, "r");
      inArchive = SevenZip.openInArchive(null,
                                         new RandomAccessFileInStream(randomAccessFile));
      ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();

      for (ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
        if (!item.isFolder() && !item.isEncrypted()
            && item.getPath().endsWith("skp")) {
          ExtractOperationResult result;
          final boolean[] append = {false};
          result = item.extractSlow(data -> {
            try {
              if (append[0]) {
                FileUtil.appendBytes(dest, data);
              } else {
                FileUtil.writeBytes(dest, data);
                append[0] = true;
              }
            } catch (IOException e) {
              e.printStackTrace();
            }
            return data.length;
          });
          if (result != ExtractOperationResult.OK) {
            return false;
          }
          break;
        }
      }
      return true;
    } catch (Exception e) {
      e.printStackTrace();
      System.err.println("Error occurs: " + e);
      return false;
    } finally {
      if (inArchive != null) {
        try {
          inArchive.close();
        } catch (SevenZipException e) {
          System.err.println("Error closing archive: " + e);
        }
      }
      if (randomAccessFile != null) {
        try {
          randomAccessFile.close();
        } catch (IOException e) {
          System.err.println("Error closing file: " + e);
        }
      }
    }
  }

}
